package com.shine.app.commons;

import java.net.URI;
import java.net.URISyntaxException;

import org.springframework.http.ContentCodingType;
import org.springframework.http.HttpAuthentication;
import org.springframework.http.HttpBasicAuthentication;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;

public class OpenTeeServiceClientImpl implements OpenTeeServiceClient {

	private Gson gson = new Gson();

	private static OpenTeeServiceClientImpl openTeeServiceClientImpl;

	public static OpenTeeServiceClientImpl getInstance() {
		if (openTeeServiceClientImpl == null) {
			synchronized (OpenTeeServiceClientImpl.class) {
				if (openTeeServiceClientImpl == null) {
					openTeeServiceClientImpl = new OpenTeeServiceClientImpl();
				}
			}
		}
		return openTeeServiceClientImpl;
	}

	public <TRequest, TResponse> TResponse execute(TRequest request,
			Class<TResponse> responseClass, String url, HttpMethod httpmethod)
			throws RestClientException, JsonSyntaxException {
		return executeUri(request, responseClass, url, httpmethod, false);
	}

	public <TRequest, TResponse> TResponse executeUri(TRequest request,
			Class<TResponse> responseClass, String url, HttpMethod httpmethod,
			boolean flag) throws RestClientException, JsonSyntaxException {
		try {
			RestTemplate restTemplate = getRestTemplate();
			HttpEntity<TRequest> requestEntity = new HttpEntity<TRequest>(
					request, makeRequestHeader());
			ResponseEntity<String> responseEntity = null;
			if (flag) {
				URI uri = new URI(url);
				responseEntity = restTemplate.exchange(uri, httpmethod,
						requestEntity, String.class);
			} else {
				responseEntity = restTemplate.exchange(url, httpmethod,
						requestEntity, String.class);
			}
			String json = responseEntity.getBody();
			return (TResponse) gson.fromJson(json, responseClass);
		} catch (RestClientException e) {
			e.printStackTrace();
		} catch (JsonSyntaxException e) {
			e.printStackTrace();
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
		return null;
	}

	protected RestTemplate getRestTemplate() {
		RestTemplate restTemplate = new RestTemplate();
		restTemplate.getMessageConverters().add(
				new StringHttpMessageConverter());
		restTemplate.getMessageConverters().add(
				new MappingJackson2HttpMessageConverter());
		return restTemplate;
	}

	private HttpHeaders makeRequestHeader() {
		HttpAuthentication authHeader = new HttpBasicAuthentication(
				Commons.AUTH_NAME, Commons.AUTH_KEY);
		HttpHeaders requestHeaders = new HttpHeaders();
		requestHeaders.setAcceptEncoding(ContentCodingType.GZIP);
		requestHeaders.setAuthorization(authHeader);
		requestHeaders.add(Urls.API_Key, Urls.API_VALUE);
		requestHeaders.setContentType(new MediaType(Commons.APPLICATION,
				Commons.JSON));
		return requestHeaders;
	}

}
